const jwt = require('jsonwebtoken');
const User = require('../models/User');
const Order = require('../models/Order');
const logger = require('./logger');

/**
 * Socket.io 服务类
 * 处理实时通信功能
 */
class SocketService {
  constructor(io) {
    this.io = io;
    this.connectedUsers = new Map(); // 存储已连接的用户
    this.userSockets = new Map(); // 用户ID到socket的映射
    this.setupMiddleware();
    this.setupEventHandlers();
  }

  /**
   * 设置中间件
   */
  setupMiddleware() {
    // Socket认证中间件
    this.io.use(async (socket, next) => {
      try {
        const token = socket.handshake.auth.token || socket.handshake.headers.authorization?.replace('Bearer ', '');
        
        if (!token) {
          return next(new Error('未提供认证令牌'));
        }

        const decoded = jwt.verify(token, process.env.JWT_SECRET);
        const user = await User.findById(decoded.id).select('-password');
        
        if (!user) {
          return next(new Error('用户不存在'));
        }

        if (!user.isActive) {
          return next(new Error('用户账户已被禁用'));
        }

        socket.userId = user._id.toString();
        socket.user = user;
        next();
      } catch (error) {
        logger.error('Socket认证失败:', error);
        next(new Error('认证失败'));
      }
    });
  }

  /**
   * 设置事件处理器
   */
  setupEventHandlers() {
    this.io.on('connection', (socket) => {
      this.handleConnection(socket);
    });
  }

  /**
   * 处理用户连接
   */
  handleConnection(socket) {
    const userId = socket.userId;
    const user = socket.user;

    // 记录用户连接
    this.connectedUsers.set(userId, {
      socketId: socket.id,
      user: user,
      connectedAt: new Date(),
      lastActivity: new Date()
    });

    this.userSockets.set(userId, socket);

    logger.info(`用户连接: ${user.name} (${userId})`);

    // 加入用户专属房间
    socket.join(`user_${userId}`);

    // 如果是护理员，加入护理员房间
    if (user.role === 'caregiver') {
      socket.join('caregivers');
    }

    // 发送连接成功消息
    socket.emit('connected', {
      message: '连接成功',
      userId: userId,
      timestamp: new Date()
    });

    // 发送未读消息和通知
    this.sendPendingNotifications(socket, userId);

    // 设置事件监听器
    this.setupSocketEvents(socket);

    // 处理断开连接
    socket.on('disconnect', () => {
      this.handleDisconnection(socket);
    });
  }

  /**
   * 设置Socket事件监听器
   */
  setupSocketEvents(socket) {
    const userId = socket.userId;

    // 加入订单房间
    socket.on('join-order', (orderId) => {
      this.handleJoinOrder(socket, orderId);
    });

    // 离开订单房间
    socket.on('leave-order', (orderId) => {
      this.handleLeaveOrder(socket, orderId);
    });

    // 发送消息
    socket.on('send-message', (data) => {
      this.handleSendMessage(socket, data);
    });

    // 更新位置
    socket.on('update-location', (data) => {
      this.handleUpdateLocation(socket, data);
    });

    // 订单状态更新
    socket.on('order-status-update', (data) => {
      this.handleOrderStatusUpdate(socket, data);
    });

    // 心跳检测
    socket.on('ping', () => {
      this.updateUserActivity(userId);
      socket.emit('pong', { timestamp: new Date() });
    });

    // 护理员位置更新（仅护理员）
    if (socket.user.role === 'caregiver') {
      socket.on('caregiver-location-update', (data) => {
        this.handleCaregiverLocationUpdate(socket, data);
      });
    }
  }

  /**
   * 处理加入订单房间
   */
  async handleJoinOrder(socket, orderId) {
    try {
      const userId = socket.userId;
      const order = await Order.findById(orderId);
      
      if (!order) {
        socket.emit('error', { message: '订单不存在' });
        return;
      }

      // 验证用户权限
      const hasPermission = order.user.toString() === userId || 
                           order.caregiver?.toString() === userId ||
                           socket.user.role === 'admin';
      
      if (!hasPermission) {
        socket.emit('error', { message: '无权限访问此订单' });
        return;
      }

      socket.join(`order_${orderId}`);
      socket.emit('joined-order', { orderId, timestamp: new Date() });
      
      // 通知房间内其他用户
      socket.to(`order_${orderId}`).emit('user-joined-order', {
        userId,
        userName: socket.user.name,
        timestamp: new Date()
      });

      logger.info(`用户 ${userId} 加入订单房间: ${orderId}`);
    } catch (error) {
      logger.error('加入订单房间失败:', error);
      socket.emit('error', { message: '加入订单房间失败' });
    }
  }

  /**
   * 处理离开订单房间
   */
  handleLeaveOrder(socket, orderId) {
    const userId = socket.userId;
    
    socket.leave(`order_${orderId}`);
    socket.emit('left-order', { orderId, timestamp: new Date() });
    
    // 通知房间内其他用户
    socket.to(`order_${orderId}`).emit('user-left-order', {
      userId,
      userName: socket.user.name,
      timestamp: new Date()
    });

    logger.info(`用户 ${userId} 离开订单房间: ${orderId}`);
  }

  /**
   * 处理发送消息
   */
  async handleSendMessage(socket, data) {
    try {
      const { orderId, message, messageType = 'text' } = data;
      const userId = socket.userId;
      const user = socket.user;

      // 验证订单权限
      const order = await Order.findById(orderId);
      if (!order) {
        socket.emit('error', { message: '订单不存在' });
        return;
      }

      const hasPermission = order.user.toString() === userId || 
                           order.caregiver?.toString() === userId;
      
      if (!hasPermission) {
        socket.emit('error', { message: '无权限发送消息' });
        return;
      }

      const messageData = {
        id: Date.now().toString(),
        orderId,
        senderId: userId,
        senderName: user.name,
        senderAvatar: user.avatar,
        message,
        messageType,
        timestamp: new Date(),
        read: false
      };

      // 发送消息到订单房间
      this.io.to(`order_${orderId}`).emit('new-message', messageData);

      // 这里可以保存消息到数据库
      // await this.saveMessage(messageData);

      logger.info(`用户 ${userId} 在订单 ${orderId} 中发送消息`);
    } catch (error) {
      logger.error('发送消息失败:', error);
      socket.emit('error', { message: '发送消息失败' });
    }
  }

  /**
   * 处理位置更新
   */
  handleUpdateLocation(socket, data) {
    const { orderId, location } = data;
    const userId = socket.userId;

    // 向订单房间广播位置更新
    socket.to(`order_${orderId}`).emit('location-update', {
      userId,
      location,
      timestamp: new Date()
    });

    this.updateUserActivity(userId);
    logger.info(`用户 ${userId} 更新位置信息`);
  }

  /**
   * 处理订单状态更新
   */
  async handleOrderStatusUpdate(socket, data) {
    try {
      const { orderId, status, message } = data;
      const userId = socket.userId;

      // 验证权限和更新订单状态的逻辑应该在控制器中处理
      // 这里只负责广播状态更新
      
      const updateData = {
        orderId,
        status,
        message,
        updatedBy: userId,
        updatedByName: socket.user.name,
        timestamp: new Date()
      };

      // 向订单房间广播状态更新
      this.io.to(`order_${orderId}`).emit('order-status-updated', updateData);

      logger.info(`订单 ${orderId} 状态更新为: ${status}`);
    } catch (error) {
      logger.error('处理订单状态更新失败:', error);
      socket.emit('error', { message: '订单状态更新失败' });
    }
  }

  /**
   * 处理护理员位置更新
   */
  handleCaregiverLocationUpdate(socket, data) {
    const { location, isWorking } = data;
    const userId = socket.userId;

    // 向所有管理员广播护理员位置
    this.io.to('admins').emit('caregiver-location-update', {
      caregiverId: userId,
      location,
      isWorking,
      timestamp: new Date()
    });

    this.updateUserActivity(userId);
    logger.info(`护理员 ${userId} 更新位置信息`);
  }

  /**
   * 处理用户断开连接
   */
  handleDisconnection(socket) {
    const userId = socket.userId;
    const user = socket.user;

    if (userId) {
      this.connectedUsers.delete(userId);
      this.userSockets.delete(userId);
      
      // 通知相关用户
      socket.broadcast.emit('user-disconnected', {
        userId,
        userName: user?.name,
        timestamp: new Date()
      });

      logger.info(`用户断开连接: ${user?.name} (${userId})`);
    }
  }

  /**
   * 发送待处理的通知
   */
  async sendPendingNotifications(socket, userId) {
    try {
      // 这里可以查询数据库中的未读通知
      // const notifications = await getUnreadNotifications(userId);
      // socket.emit('pending-notifications', notifications);
      
      socket.emit('pending-notifications', []);
    } catch (error) {
      logger.error('发送待处理通知失败:', error);
    }
  }

  /**
   * 更新用户活动时间
   */
  updateUserActivity(userId) {
    const userConnection = this.connectedUsers.get(userId);
    if (userConnection) {
      userConnection.lastActivity = new Date();
    }
  }

  /**
   * 向特定用户发送消息
   */
  sendToUser(userId, event, data) {
    const socket = this.userSockets.get(userId);
    if (socket) {
      socket.emit(event, data);
      return true;
    }
    return false;
  }

  /**
   * 向订单相关用户发送消息
   */
  sendToOrder(orderId, event, data) {
    this.io.to(`order_${orderId}`).emit(event, data);
  }

  /**
   * 向所有护理员发送消息
   */
  sendToCaregivers(event, data) {
    this.io.to('caregivers').emit(event, data);
  }

  /**
   * 获取在线用户列表
   */
  getOnlineUsers() {
    const onlineUsers = [];
    this.connectedUsers.forEach((connection, userId) => {
      onlineUsers.push({
        userId,
        user: {
          id: connection.user._id,
          name: connection.user.name,
          avatar: connection.user.avatar,
          role: connection.user.role
        },
        connectedAt: connection.connectedAt,
        lastActivity: connection.lastActivity
      });
    });
    return onlineUsers;
  }

  /**
   * 检查用户是否在线
   */
  isUserOnline(userId) {
    return this.connectedUsers.has(userId);
  }

  /**
   * 获取在线用户数量
   */
  getOnlineUserCount() {
    return this.connectedUsers.size;
  }

  /**
   * 清理非活跃连接
   */
  cleanupInactiveConnections() {
    const now = new Date();
    const inactiveThreshold = 30 * 60 * 1000; // 30分钟

    this.connectedUsers.forEach((connection, userId) => {
      if (now - connection.lastActivity > inactiveThreshold) {
        const socket = this.userSockets.get(userId);
        if (socket) {
          socket.disconnect(true);
        }
        this.connectedUsers.delete(userId);
        this.userSockets.delete(userId);
        logger.info(`清理非活跃连接: ${userId}`);
      }
    });
  }
}

module.exports = SocketService;